Skip to content

Commit

Permalink
Merge pull request #4206 from tloncorp/po/tlon-3007-fix-go-to-group-b…
Browse files Browse the repository at this point in the history
…utton-in-preview-sheet

group previews: fix go to groups button
  • Loading branch information
latter-bolden authored Nov 20, 2024
2 parents 46e5103 + a8fc485 commit 77bc0fc
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ module.exports = {
message:
'Please use the useTypedReset() hook instead of importing reset from @react-navigation/native for type safety.',
},
{
selector: 'ImportDeclaration > Literal[value=/^packages/]',
message:
'Do not import directly from the "packages" directory. Use the package name (or relative path, if within the same package) instead.',
},
],
},
};
12 changes: 12 additions & 0 deletions packages/app/features/top/ChatListScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
ChatOptionsProvider,
ChatOptionsSheet,
ChatOptionsSheetMethods,
GroupPreviewAction,
GroupPreviewSheet,
InviteUsersSheet,
NavBarView,
Expand All @@ -27,6 +28,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { TLON_EMPLOYEE_GROUP } from '../../constants';
import { useChatSettingsNavigation } from '../../hooks/useChatSettingsNavigation';
import { useCurrentUserId } from '../../hooks/useCurrentUser';
import { useGroupActions } from '../../hooks/useGroupActions';
import { useFeatureFlag } from '../../lib/featureFlags';
import type { RootStackParamList } from '../../navigation/types';
import { screenNameFromChannelId } from '../../navigation/utils';
Expand Down Expand Up @@ -91,6 +93,7 @@ export function ChatListScreenView({
const { data: chats } = store.useCurrentChats({
enabled: isFocused,
});
const { performGroupAction } = useGroupActions();

const currentUser = useCurrentUserId();

Expand Down Expand Up @@ -286,6 +289,14 @@ export function ChatListScreenView({
setShowSearchInput(!showSearchInput);
}, [showSearchInput]);

const handleGroupAction = useCallback(
(action: GroupPreviewAction, group: db.Group) => {
performGroupAction(action, group);
setSelectedGroupId(null);
},
[performGroupAction]
);

return (
<RequestsProvider
usePostReference={store.usePostReference}
Expand Down Expand Up @@ -345,6 +356,7 @@ export function ChatListScreenView({
open={!!selectedGroup}
onOpenChange={handleGroupPreviewSheetOpenChange}
group={selectedGroup ?? undefined}
onActionComplete={handleGroupAction}
/>
<InviteUsersSheet
open={inviteSheetGroup !== null}
Expand Down
12 changes: 12 additions & 0 deletions packages/app/features/top/UserProfileScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type * as db from '@tloncorp/shared/db';
import * as store from '@tloncorp/shared/store';
import {
AppDataContextProvider,
GroupPreviewAction,
GroupPreviewSheet,
NavigationProvider,
UserProfileScreenView,
Expand All @@ -11,6 +12,7 @@ import { useState } from 'react';
import { useCallback } from 'react';

import { useCurrentUserId } from '../../hooks/useCurrentUser';
import { useGroupActions } from '../../hooks/useGroupActions';
import { RootStackParamList } from '../../navigation/types';
import { useResetToDm } from '../../navigation/utils';
import { useConnectionStatus } from './useConnectionStatus';
Expand All @@ -24,6 +26,7 @@ export function UserProfileScreen({ route: { params }, navigation }: Props) {
const connectionStatus = useConnectionStatus(userId);
const [selectedGroup, setSelectedGroup] = useState<db.Group | null>(null);
const resetToDm = useResetToDm();
const { performGroupAction } = useGroupActions();

const handleGoToDm = useCallback(
async (participants: string[]) => {
Expand All @@ -43,6 +46,14 @@ export function UserProfileScreen({ route: { params }, navigation }: Props) {
navigation.push('EditProfile');
}, [navigation]);

const handleGroupAction = useCallback(
(action: GroupPreviewAction, group: db.Group) => {
setSelectedGroup(null);
performGroupAction(action, group);
},
[performGroupAction]
);

return (
<AppDataContextProvider
currentUserId={currentUserId}
Expand All @@ -60,6 +71,7 @@ export function UserProfileScreen({ route: { params }, navigation }: Props) {
open={selectedGroup !== null}
onOpenChange={handleGroupPreviewSheetOpenChange}
group={selectedGroup ?? undefined}
onActionComplete={handleGroupAction}
/>
</NavigationProvider>
</AppDataContextProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default Object.fromEntries(
open={true}
onOpenChange={() => {}}
group={group}
onActionComplete={() => {}}
/>,
];
})
Expand Down
13 changes: 4 additions & 9 deletions packages/app/hooks/useGroupActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,19 @@ import { useCallback } from 'react';
import { useGroupNavigation } from './useGroupNavigation';

export const useGroupActions = () => {
const { goToChannel, goToHome } = useGroupNavigation();
const { goToHome, goToGroupChannels } = useGroupNavigation();

const performGroupAction = useCallback(
async (action: GroupPreviewAction, updatedGroup: db.Group) => {
if (action === 'goTo' && updatedGroup.lastPost?.channelId) {
const channel = await db.getChannel({
id: updatedGroup.lastPost.channelId,
});
if (channel) {
goToChannel(channel);
}
if (action === 'goTo') {
goToGroupChannels(updatedGroup.id);
}

if (action === 'joined') {
goToHome();
}
},
[goToChannel, goToHome]
[goToGroupChannels, goToHome]
);

return {
Expand Down
10 changes: 10 additions & 0 deletions packages/app/hooks/useGroupNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import * as db from '@tloncorp/shared/db';
import { useCallback } from 'react';

import { RootStackParamList } from '../navigation/types';
import { useResetToGroup } from '../navigation/utils';

export const useGroupNavigation = () => {
const navigation = useNavigation<
// @ts-expect-error - TODO: pass navigation handlers into context
NativeStackNavigationProp<RootStackParamList, 'Channel' | 'Post'>
>();
const resetToGroup = useResetToGroup();

const goToChannel = useCallback(
async (
Expand All @@ -24,6 +26,13 @@ export const useGroupNavigation = () => {
[navigation]
);

const goToGroupChannels = useCallback(
async (groupId: string) => {
resetToGroup(groupId);
},
[resetToGroup]
);

const goToHome = useCallback(() => {
navigation.navigate('ChatList');
}, [navigation]);
Expand All @@ -39,5 +48,6 @@ export const useGroupNavigation = () => {
goToChannel,
goToHome,
goToContactHostedGroups,
goToGroupChannels,
};
};
11 changes: 11 additions & 0 deletions packages/app/navigation/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ export function useResetToDm() {
};
}

export function useResetToGroup() {
const reset = useTypedReset();

return function resetToGroup(groupId: string) {
reset([
{ name: 'ChatList' },
{ name: 'GroupChannels', params: { groupId } },
]);
};
}

export function screenNameFromChannelId(channelId: string) {
return logic.isDmChannelId(channelId)
? 'DM'
Expand Down
3 changes: 3 additions & 0 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"main": "index.ts",
"private": true,
"scripts": {
"lint": "eslint ./",
"lint:fix": "eslint ./ --fix --quiet",
"lint:format": "prettier ./ --write",
"test": "vitest --watch false"
},
"dependencies": {
Expand Down
22 changes: 4 additions & 18 deletions packages/ui/src/components/ContentReference/ContentReference.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { ContentReference } from '@tloncorp/shared/api';
import * as db from '@tloncorp/shared/db';
import { getChannelType } from '@tloncorp/shared/urbit';
import React, { useState } from 'react';
import React from 'react';
import { ComponentProps, useCallback } from 'react';
import { View, XStack, styled } from 'tamagui';

Expand All @@ -11,7 +11,6 @@ import { useRequests } from '../../contexts/requests';
import { ContactAvatar, GroupAvatar } from '../Avatar';
import { useContactName } from '../ContactNameV2';
import { GalleryContentRenderer } from '../GalleryPost';
import { GroupPreviewSheet } from '../GroupPreviewSheet';
import { IconType } from '../Icon';
import { ListItem } from '../ListItem';
import { useBoundHandler } from '../ListItem/listItemUtils';
Expand Down Expand Up @@ -76,28 +75,21 @@ export function PostReferenceLoader({
postId: string;
replyId?: string;
}) {
const [selectedGroup, setSelectedGroup] = useState<db.Group | null>(null);
const { usePostReference, useChannel, useGroup } = useRequests();
const postQuery = usePostReference({
postId: replyId ? replyId : postId,
channelId: channelId,
});
const { data: channel } = useChannel({ id: channelId });
const { data: group } = useGroup(channel?.groupId ?? '');
const { onPressRef } = useNavigation();
const { onPressRef, onPressGroupRef } = useNavigation();
const handlePress = useCallback(async () => {
if (channel && postQuery.data && group && group.currentUserIsMember) {
onPressRef?.(channel, postQuery.data);
} else if (group) {
setSelectedGroup(group ?? null);
onPressGroupRef?.(group);
}
}, [channel, onPressRef, postQuery.data, group]);

const handleGroupPreviewSheetOpenChange = useCallback((open: boolean) => {
if (!open) {
setSelectedGroup(null);
}
}, []);
}, [channel, onPressRef, postQuery.data, group, onPressGroupRef]);

return (
<>
Expand All @@ -111,12 +103,6 @@ export function PostReferenceLoader({
onPress={openOnPress ? handlePress : undefined}
{...props}
/>

<GroupPreviewSheet
open={selectedGroup !== null}
onOpenChange={handleGroupPreviewSheetOpenChange}
group={selectedGroup ?? undefined}
/>
</>
);
}
Expand Down
8 changes: 6 additions & 2 deletions packages/ui/src/components/GroupPreviewSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { LoadingSpinner } from './LoadingSpinner';
interface Props {
open: boolean;
onOpenChange: (open: boolean) => void;
onActionComplete?: (action: GroupPreviewAction, group: db.Group) => void;
onActionComplete: (action: GroupPreviewAction, group: db.Group) => void;
group?: db.Group;
}

Expand Down Expand Up @@ -44,7 +44,11 @@ function GroupPreviewSheetComponent({

const actionHandler = useCallback(
(action: GroupPreviewAction, updatedGroup: db.Group) => {
onActionComplete?.(action, updatedGroup);
// Delay the action complete callback to allow the sheet to close.
// If we don't do this the app will crash.
setTimeout(() => {
onActionComplete?.(action, updatedGroup);
}, 100);
onOpenChange(false);
},
[onActionComplete, onOpenChange]
Expand Down

0 comments on commit 77bc0fc

Please sign in to comment.