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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jest.mock('@tanstack/react-query', () => ({ useQuery: (...args:any[]) => queryMo
jest.mock('next/link', () => ({ __esModule: true, default: (p:any) => <a {...p}>{p.children}</a> }));
jest.mock('@/components/waves/header/WaveHeaderFollow', () => ({ __esModule: true, default: () => <div data-testid="wave-follow" />, WaveFollowBtnSize:{} }));
jest.mock('@/components/brain/notifications/NotificationsFollowBtn', () => ({ __esModule: true, default: () => <div data-testid="follow-btn" /> }));
jest.mock('@/helpers/image.helpers', () => ({ getScaledImageUri: () => 'scaled.jpg', ImageScale:{} }));
jest.mock('@/helpers/image.helpers', () => ({ getScaledImageUri: () => '/scaled.jpg', ImageScale:{} }));
jest.mock('@/helpers/Helpers', () => ({ getTimeAgoShort: () => '1m' }));

const notification = {
Expand Down Expand Up @@ -35,5 +35,5 @@ it('renders wave data and links', () => {
expect(screen.getByTestId('wave-follow')).toBeInTheDocument();
expect(screen.getByTestId('follow-btn')).toBeInTheDocument();
const img = screen.getByRole('img');
expect(img).toHaveAttribute('src', 'scaled.jpg');
expect(img.getAttribute('src')).toContain('scaled.jpg');
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ jest.mock('next/navigation', () => ({
usePathname: jest.fn(),
}));

jest.mock('@/hooks/useDeviceInfo', () => ({
__esModule: true,
default: () => ({ isApp: false }),
}));

jest.mock('@/components/brain/notifications/subcomponents/NotificationHeader', () => ({
__esModule: true,
default: ({ children }: any) => <div data-testid="notification-header">{children}</div>,
}));

jest.mock('@/components/brain/notifications/NotificationsFollowBtn', () => ({
__esModule: true,
default: () => <div data-testid="follow-btn" />,
}));

jest.mock('@/components/waves/drops/Drop', () => ({
__esModule: true,
default: (props: any) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ jest.mock('next/navigation', () => ({
usePathname: jest.fn(),
}));

jest.mock('@/hooks/useDeviceInfo', () => ({
__esModule: true,
default: () => ({ isApp: false }),
}));

jest.mock('@/components/waves/drops/Drop', () => ({
__esModule: true,
DropLocation: { MY_STREAM: 'MY_STREAM' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ jest.mock('next/navigation', () => ({
useSearchParams: jest.fn(),
usePathname: jest.fn(),
}));
jest.mock('@/hooks/useDeviceInfo', () => ({
__esModule: true,
default: () => ({ isApp: false }),
}));

import NotificationIdentityMentioned from '@/components/brain/notifications/identity-mentioned/NotificationIdentityMentioned';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
"use client";

import { getTimeAgoShort } from "@/helpers/Helpers";
import { UserFollowBtnSize } from "@/components/user/utils/UserFollowBtn";
import NotificationsFollowBtn from "../NotificationsFollowBtn";
import { DropSize, ExtendedDrop } from "@/helpers/waves/drop.helpers";
import { INotificationDropQuoted } from "@/types/feed.types";
import { ActiveDropState } from "@/types/dropInteractionTypes";
import Drop, {
DropInteractionParams,
DropLocation,
} from "@/components/waves/drops/Drop";
import { useRouter } from "next/navigation";
import { ApiDrop } from "@/generated/models/ApiDrop";
import useDeviceInfo from "@/hooks/useDeviceInfo";
import { getWaveRoute } from "@/helpers/navigation.helpers";
import NotificationHeader from "../subcomponents/NotificationHeader";
import { useWaveNavigation } from "../utils/navigationUtils";

export default function NotificationDropQuoted({
notification,
Expand All @@ -25,18 +27,7 @@ export default function NotificationDropQuoted({
readonly onQuote: (param: DropInteractionParams) => void;
readonly onDropContentClick?: (drop: ExtendedDrop) => void;
}) {
const router = useRouter();
const { isApp } = useDeviceInfo();

const navigateToWave = (
waveId: string,
serialNo: number,
isDirectMessage: boolean
) => {
router.push(
getWaveRoute({ waveId, serialNo, isDirectMessage, isApp })
);
};
const { navigateToWave } = useWaveNavigation();

const onReplyClick = (serialNo: number) => {
const baseWave = notification.related_drops[0].wave as any;
Expand All @@ -53,25 +44,47 @@ export default function NotificationDropQuoted({
};

return (
<Drop
drop={{
type: DropSize.FULL,
...notification.related_drops[0],
stableKey: "",
stableHash: "",
}}
previousDrop={null}
nextDrop={null}
showWaveInfo={true}
showReplyAndQuote={true}
activeDrop={activeDrop}
location={DropLocation.MY_STREAM}
dropViewDropId={null}
onReply={onReply}
onQuote={onQuote}
onReplyClick={onReplyClick}
onQuoteClick={onQuoteClick}
onDropContentClick={onDropContentClick}
/>
<div className="tw-w-full tw-flex tw-flex-col tw-space-y-2">
<NotificationHeader
author={notification.related_drops[0].author}
actions={
<NotificationsFollowBtn
profile={notification.related_drops[0].author}
size={UserFollowBtnSize.SMALL}
/>
}
>
<span className="tw-text-iron-400 tw-font-normal tw-text-sm">
quoted you
</span>
<span className="tw-text-sm tw-text-iron-300 tw-font-normal tw-whitespace-nowrap">
<span className="tw-font-bold tw-mr-1 tw-text-xs tw-text-iron-400">
&#8226;
</span>
{getTimeAgoShort(notification.created_at)}
</span>
</NotificationHeader>

<Drop
drop={{
type: DropSize.FULL,
...notification.related_drops[0],
stableKey: "",
stableHash: "",
}}
previousDrop={null}
nextDrop={null}
showWaveInfo={true}
showReplyAndQuote={true}
activeDrop={activeDrop}
location={DropLocation.MY_STREAM}
dropViewDropId={null}
onReply={onReply}
onQuote={onQuote}
onReplyClick={onReplyClick}
onQuoteClick={onQuoteClick}
onDropContentClick={onDropContentClick}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
"use client";

import { getScaledImageUri, ImageScale } from "@/helpers/image.helpers";
import { getTimeAgoShort, numberWithCommas } from "@/helpers/Helpers";
import Link from "next/link";
import Drop, {
DropInteractionParams,
DropLocation,
} from "@/components/waves/drops/Drop";
import { ActiveDropState } from "@/types/dropInteractionTypes";
import { useRouter } from "next/navigation";
import { ApiDrop } from "@/generated/models/ApiDrop";
import { DropSize, ExtendedDrop } from "@/helpers/waves/drop.helpers";
import NotificationsFollowBtn from "../NotificationsFollowBtn";
Expand All @@ -18,9 +15,8 @@ import type {
INotificationDropVoted,
INotificationDropReacted,
} from "@/types/feed.types";
import UserProfileTooltipWrapper from "@/components/utils/tooltip/UserProfileTooltipWrapper";
import useDeviceInfo from "@/hooks/useDeviceInfo";
import { getWaveRoute } from "@/helpers/navigation.helpers";
import NotificationHeader from "../subcomponents/NotificationHeader";
import { useWaveNavigation } from "../utils/navigationUtils";

export const getNotificationVoteColor = (vote: number) => {
if (vote > 0) return "tw-text-green";
Expand All @@ -45,9 +41,8 @@ export default function NotificationDropReacted({
onQuote,
onDropContentClick,
}: Props) {
const router = useRouter();
const { navigateToWave } = useWaveNavigation();
const { findCustomEmoji, findNativeEmoji } = useEmoji();
const { isApp } = useDeviceInfo();

// Determine if this notification is a "vote" or a "reaction"
const isVoted =
Expand All @@ -66,20 +61,13 @@ export default function NotificationDropReacted({

actionElement = (
<>
<UserProfileTooltipWrapper user={notification.related_identity.handle ?? ""}>
<Link
href={`/${notification.related_identity.handle}`}
className="tw-no-underline tw-font-semibold tw-text-sm tw-text-iron-50">
{notification.related_identity.handle}
</Link>
</UserProfileTooltipWrapper>
<span className="tw-text-iron-400 tw-font-normal tw-text-sm">
rated
</span>
<span
className={`${getNotificationVoteColor(
voteValue
)} tw-pl-1 tw-font-medium tw-text-sm`}>
)} tw-font-medium tw-text-sm`}>
{voteValue > 0 && "+"}
{numberWithCommas(voteValue)}
</span>
Expand Down Expand Up @@ -125,13 +113,6 @@ export default function NotificationDropReacted({

actionElement = (
<>
<UserProfileTooltipWrapper user={notification.related_identity.handle ?? ""}>
<Link
href={`/${notification.related_identity.handle}`}
className="tw-no-underline tw-font-semibold tw-text-sm tw-text-iron-50">
{notification.related_identity.handle}
</Link>
</UserProfileTooltipWrapper>
<span className="tw-text-iron-400 tw-font-normal tw-text-sm">
reacted
</span>
Expand All @@ -152,81 +133,50 @@ export default function NotificationDropReacted({
const baseIsDm = baseWave?.chat?.scope?.group?.is_direct_message ?? false;

const onReplyClick = (serialNo: number) => {
router.push(
getWaveRoute({
waveId: baseWave.id,
serialNo,
isDirectMessage: baseIsDm,
isApp,
})
);
navigateToWave(baseWave.id, serialNo, baseIsDm);
};

const onQuoteClick = (quote: ApiDrop) => {
const quoteWave = quote.wave as any;
const isDirectMessage =
quoteWave?.chat?.scope?.group?.is_direct_message ?? baseIsDm;

router.push(
getWaveRoute({
waveId: quote.wave.id,
serialNo: quote.serial_no,
isDirectMessage,
isApp,
})
);
navigateToWave(quote.wave.id, quote.serial_no, isDirectMessage);
};

return (
<div className="tw-flex tw-gap-x-3 tw-w-full">
<div className="tw-space-y-2 tw-w-full">
<div className="tw-flex tw-justify-between tw-gap-x-4 tw-gap-y-1">
<div className="tw-flex-1 tw-flex tw-gap-x-2 tw-items-center">
<div className="tw-h-7 tw-w-7">
{notification.related_identity.pfp ? (
<img
src={getScaledImageUri(
notification.related_identity.pfp,
ImageScale.W_AUTO_H_50
)}
alt={notification.related_identity.handle ?? ""}
className="tw-flex-shrink-0 tw-object-contain tw-h-full tw-w-full tw-rounded-md tw-bg-iron-800 tw-ring-1 tw-ring-iron-700"
/>
) : (
<div className="tw-flex-shrink-0 tw-object-contain tw-h-full tw-w-full tw-rounded-md tw-bg-iron-800 tw-ring-1 tw-ring-iron-700" />
)}
</div>
<span className="tw-inline-flex tw-flex-wrap tw-gap-x-1 tw-items-center">
{actionElement}
</span>
</div>

<div className="tw-w-full tw-flex tw-flex-col tw-space-y-2">
<NotificationHeader
author={notification.related_identity}
actions={
<NotificationsFollowBtn
profile={notification.related_identity}
size={UserFollowBtnSize.SMALL}
/>
</div>

<Drop
drop={{
type: DropSize.FULL,
...notification.related_drops[0],
stableKey: "",
stableHash: "",
}}
previousDrop={null}
nextDrop={null}
showWaveInfo={true}
showReplyAndQuote={true}
activeDrop={activeDrop}
location={DropLocation.MY_STREAM}
dropViewDropId={null}
onReply={onReply}
onQuote={onQuote}
onReplyClick={onReplyClick}
onQuoteClick={onQuoteClick}
onDropContentClick={onDropContentClick}
/>
</div>
}
>
{actionElement}
</NotificationHeader>

<Drop
drop={{
type: DropSize.FULL,
...notification.related_drops[0],
stableKey: "",
stableHash: "",
}}
previousDrop={null}
nextDrop={null}
showWaveInfo={true}
showReplyAndQuote={true}
activeDrop={activeDrop}
location={DropLocation.MY_STREAM}
dropViewDropId={null}
onReply={onReply}
onQuote={onQuote}
onReplyClick={onReplyClick}
onQuoteClick={onQuoteClick}
onDropContentClick={onDropContentClick}
/>
</div>
);
}
Loading