Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/app/home/[full-tweet]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ function Page() {
</div>
);

const isReply = tweet?.type === 'REPLY';

return (
<>
<FullTweet data={tweet} id={id} />
{/* <Replies id={tweet?.postId || 0} /> */}
</>
<div className="overflow-visible">
<FullTweet data={tweet} id={id} isReply={isReply} />
</div>
);
}

Expand Down
8 changes: 6 additions & 2 deletions src/components/ui/forms/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ export interface FormHandlers {
}

export interface FormContainerProps
extends GenericAuthFormProps, FormState, FormHandlers {
extends GenericAuthFormProps,
FormState,
FormHandlers {
displayMode: 'modal' | 'fullpage';
onClose?: () => void;
className?: string;
Expand Down Expand Up @@ -150,7 +152,9 @@ export interface SocialLoginSectionProps {
}

export interface FormContentProps
extends GenericAuthFormProps, FormState, FormHandlers {
extends GenericAuthFormProps,
FormState,
FormHandlers {
onSwitchModal?: (newType: AuthModalType) => void;
loading: boolean;
isFormValid: boolean;
Expand Down
7 changes: 4 additions & 3 deletions src/components/ui/input/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ export interface CharCounterProps {
maxLength: number;
}

export interface InputBaseProps extends React.HTMLAttributes<
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
> {
export interface InputBaseProps
extends React.HTMLAttributes<
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
> {
// loosened ref type to support both input and textarea refs
inputRef?: React.Ref<
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
Expand Down
2 changes: 1 addition & 1 deletion src/features/layout/components/LayoutWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default function LayoutWrapper({
)}

<main className="flex flex-1 flex-row min-h-screen max-w-[1100px] w-full">
<div className="border-x-border border-x sm:w-[560px] w-full flex-1 min-w-0 overflow-hidden">
<div className="border-x-border border-x sm:w-[560px] w-full flex-1 min-w-0 overflow-visible">
{children}
</div>

Expand Down
10 changes: 6 additions & 4 deletions src/features/onboarding/hooks/useOnboarding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,9 @@ describe('useOnboarding hooks', () => {
});

it('should clear user cache on success', async () => {
const { authApi } =
await import('@/features/authentication/services/authApi');
const { authApi } = await import(
'@/features/authentication/services/authApi'
);
(onboardingApi.updateDateOfBirth as any).mockResolvedValueOnce(
mockResponse
);
Expand Down Expand Up @@ -332,8 +333,9 @@ describe('useOnboarding hooks', () => {
});

it('should clear user cache on success', async () => {
const { authApi } =
await import('@/features/authentication/services/authApi');
const { authApi } = await import(
'@/features/authentication/services/authApi'
);
(onboardingApi.updateInterests as any).mockResolvedValueOnce(
mockResponse
);
Expand Down
5 changes: 3 additions & 2 deletions src/features/profile/hooks/__tests__/profileQueries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -792,8 +792,9 @@ describe('profileQueries', () => {
);
});
it('should throw error when profile User.id is missing', async () => {
const { useProfileContext } =
await import('@/app/[username]/ProfileProvider');
const { useProfileContext } = await import(
'@/app/[username]/ProfileProvider'
);
vi.mocked(useProfileContext).mockReturnValue({
profile: null as any,
isLoading: false,
Expand Down
2 changes: 1 addition & 1 deletion src/features/timeline/components/AddPostSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function AddPostSection() {
console.log(tweetFormData.getAll('media'));
console.log(media);
console.log(mentions);
const mentionsId = mentions.map((mention) => mention.id + 1);
const mentionsId = mentions.map((mention) => mention.id);

const allMentions = mentionsId.join(',');
tweetFormData.append(TweetFormDataKeys.MENTIONS, allMentions);
Expand Down
2 changes: 1 addition & 1 deletion src/features/timeline/components/Mention.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function Mention() {
if (totalProfiles && pages) {
// setMention(pages[0].data[0].User.username + '');
setIsDone(
pages[0].data[0].User.username + ' ' + pages[0].data[0]
pages[0].data[0].User.username + ' ' + pages[0].data[0].user_id
);

console.log(pages[0].data[0].User.username);
Expand Down
32 changes: 29 additions & 3 deletions src/features/timeline/optimistics/Tweets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,11 @@ export function useOptimisticTweet() {
const search = useSearch();
const path = usePathname();
const isHome = path?.startsWith('/home');
const isFullTweet = path?.startsWith('/home/');

// Extract the tweet ID from the path (e.g., /home/123 -> 123)
const extractedId = isFullTweet && path ? parseInt(path.split('/')[2]) : -1;

const isInterest = path?.startsWith('/explore/');
const { setBlockedFlag } = useActions();
const isProfile = path?.startsWith(`/${username}`);
Expand All @@ -632,18 +637,39 @@ export function useOptimisticTweet() {
}[];
oldTweet: TimelineFeed | undefined;
}> => {
if (tweetId)
if (extractedId !== -1 && isFullTweet) {
queryClient.setQueryData(
TWEET_QUERY_KEYS.tweetById(tweetId),
TWEET_QUERY_KEYS.tweetById(extractedId),
(old: any) => {
if (!old) return old;
console.log('isFullTweet', isFullTweet);
if (
isFullTweet &&
old?.data[0]?.originalPostData?.postId === tweetId
) {
console.log('here');
const newOriginalData = updateTweet(
type,
old.data[0].originalPostData,
old.data[0].originalPostData.userId
);
return {
...old,
data: [
{
...old.data[0],
originalPostData: newOriginalData,
},
],
};
}
return {
...old,
data: [updateTweet(type, old.data[0], userId)],
};
}
);

}
const tabsFeeds: {
queryKey: QueryKeyType;
previousFeed: FeedType | ExplorePersonalizedFeedDtoResponse | undefined;
Expand Down
19 changes: 16 additions & 3 deletions src/features/tweets/components/FullTweet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ import AddTweet from '@/features/timeline/components/AddTweet';
import { ADD_TWEET } from '@/features/timeline/constants/tweetConstants';
import { useActions } from '@/features/timeline/store/useTimelineStore';
import { useRealTimeTweets } from '@/features/timeline/hooks/useRealTimeTweets';
function FullTweet({ data, id }: { data: TimelineFeed | null; id: number }) {
function FullTweet({
data,
id,
isReply,
}: {
data: TimelineFeed | null;
id: number;
isReply: boolean;
}) {
const router = useRouter();
const [showBlockModal, setShowBlockModal] = useState(false);
const [blockAction, setBlockAction] = useState<'block' | 'unblock' | null>(
Expand Down Expand Up @@ -270,8 +278,13 @@ function FullTweet({ data, id }: { data: TimelineFeed | null; id: number }) {
isRepostedByMe: data.isRepostedByMe,
};
return (
<div>
<Header />
<div className="relative">
<div>
<Header />
</div>
{isReply && data.originalPostData && (
<Tweet data={data.originalPostData} />
)}
<div className="mx-auto p-4 text-white relative ">
<div className="flex items-start justify-between">
<div className="flex space-x-3">
Expand Down
10 changes: 5 additions & 5 deletions src/features/tweets/components/Tweet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Action from './Action';
import DropDown from './DropDown';
import Timing from './Timing';
import { useRouter } from 'next/navigation';
import { TimelineFeed } from '@/features/timeline/types/api';
import { TimelineFeed, TimelineTweet } from '@/features/timeline/types/api';
import { useTweetStore } from '../store/tweetStore';
import { DropIcon, RetweetIcon } from '@/components/ui/icons/UIIcons';
import { GrokIcon } from '@/components/ui/icons/BrandIcons';
Expand All @@ -29,7 +29,7 @@ export default function Tweet({
showColumn = false,
showUpperColumn = false,
}: {
data: TimelineFeed;
data: TimelineFeed | TimelineTweet;
inProfile?: boolean;
showBorder?: boolean;
showColumn?: boolean;
Expand Down Expand Up @@ -149,8 +149,8 @@ export default function Tweet({

const actionsStats = {
postId: dataViewd.postId,
isRepost: data.isRepost,
isQuote: data.isQuote,
isRepost: data.isRepost || false,
isQuote: data.isQuote || false,
userId: data.userId,
likesCount: dataViewd.likesCount,
type: data.type,
Expand Down Expand Up @@ -190,7 +190,7 @@ export default function Tweet({

const deleteTweetMutation: ReturnType<typeof useDeleteTweet> = useDeleteTweet(
dataViewd.postId,
actionsStats.isRepost,
actionsStats.isRepost || false,
actionsStats.userId,
actionsStats.parentId,
actionsStats.type
Expand Down
4 changes: 2 additions & 2 deletions src/features/tweets/tests/FullTweet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ describe('FullTweet Component', () => {
it('should render tweet content', () => {
render(
<QueryClientProvider client={queryClient}>
<FullTweet data={mockData} id={1} />
<FullTweet data={mockData} id={1} isReply={false} />
</QueryClientProvider>
);

Expand All @@ -155,7 +155,7 @@ describe('FullTweet Component', () => {
it('should show loader when data is null', () => {
render(
<QueryClientProvider client={queryClient}>
<FullTweet data={null} id={1} />
<FullTweet data={null} id={1} isReply={false} />
</QueryClientProvider>
);

Expand Down
13 changes: 7 additions & 6 deletions src/features/tweets/tests/Timing.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ describe('Timing Component', () => {
expect(dateElements.length).toBeGreaterThan(0);
});

// it('should not show hover tooltip when hover is false', () => {
// const time = new Date().toISOString();
// render(<Timing time={time} hover={false} />);
it('should not show hover tooltip when hover is false', () => {
const time = new Date().toISOString();
render(<Timing time={time} hover={false} />);

// const timingElement = screen.getByText(/\d+[mhs]/);
// expect(timingElement).not.toHaveAttribute('title');
// });
// The component renders "Just now" for current time
const timingElement = screen.getByText('Just now');
expect(timingElement).toBeInTheDocument();
});
});
Loading