Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 0 additions & 3 deletions app/waves/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import WavesPageClient from "./page.client";
import { Time } from "@/helpers/time";
import { QueryKey } from "@/components/react-query-wrapper/ReactQueryWrapper";
import { cookies } from "next/headers";
import { unstable_noStore as noStore } from "next/cache";
import type { Metadata } from "next";
import { formatAddress } from "@/helpers/Helpers";
import { formatCount } from "@/helpers/format.helpers";
Expand Down Expand Up @@ -57,7 +56,6 @@ export default async function WavesPage({
}: {
readonly searchParams: Promise<{ wave?: string; drop?: string }>;
}) {
noStore();
const resolvedParams = await searchParams;
const cookieStore = await cookies();
const context = await fetchWaveContext(resolvedParams.wave ?? null, cookieStore);
Expand Down Expand Up @@ -97,7 +95,6 @@ export async function generateMetadata({
}: {
readonly searchParams: Promise<{ wave?: string }>;
}): Promise<Metadata> {
noStore();
const resolvedParams = await searchParams;
const waveId = resolvedParams.wave ?? null;

Expand Down
55 changes: 32 additions & 23 deletions components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"use client";

import React, { useMemo } from "react";
import React, { useMemo, useCallback } from "react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { usePrefetchWaveData } from "@/hooks/usePrefetchWaveData";
import { ApiWaveType } from "@/generated/models/ApiWaveType";
import WavePicture from "@/components/waves/WavePicture";
Expand All @@ -11,6 +10,7 @@ import { MinimalWave } from "@/contexts/wave/hooks/useEnhancedWavesList";
import BrainLeftSidebarWavePin from "./BrainLeftSidebarWavePin";
import { formatAddress, isValidEthAddress } from "../../../../helpers/Helpers";
import useDeviceInfo from "../../../../hooks/useDeviceInfo";
import { useMyStream } from "@/contexts/wave/MyStreamContext";
import {
getWaveHomeRoute,
getWaveRoute,
Expand All @@ -29,8 +29,7 @@ const BrainLeftSidebarWave: React.FC<BrainLeftSidebarWaveProps> = ({
showPin = true,
isDirectMessage = false,
}) => {
const router = useRouter();
const searchParams = useSearchParams();
const { activeWave } = useMyStream();
const prefetchWaveData = usePrefetchWaveData();
const { isApp } = useDeviceInfo();
const isDropWave = wave.type !== ApiWaveType.Chat;
Expand All @@ -55,30 +54,40 @@ const BrainLeftSidebarWave: React.FC<BrainLeftSidebarWaveProps> = ({
return wave.name;
}, [wave.name, wave.type]);

const getHref = (waveId: string) => {
const currentWaveId = searchParams?.get("wave") ?? undefined;
if (currentWaveId === waveId) {
const activeWaveId = activeWave.id;

const href = useMemo(() => {
if (activeWaveId === wave.id) {
return getWaveHomeRoute({ isDirectMessage, isApp });
}
return getWaveRoute({ waveId, isDirectMessage, isApp });
};
return getWaveRoute({ waveId: wave.id, isDirectMessage, isApp });
}, [activeWaveId, isApp, isDirectMessage, wave.id]);

const haveNewDrops = wave.newDropsCount.count > 0;

const onWaveHover = (waveId: string) => {
const currentWaveId = searchParams?.get("wave") ?? undefined;
if (waveId !== currentWaveId) {
onHover(waveId);
prefetchWaveData(waveId);
const onWaveHover = useCallback(() => {
if (wave.id !== activeWaveId) {
onHover(wave.id);
prefetchWaveData(wave.id);
}
};
}, [activeWaveId, onHover, prefetchWaveData, wave.id]);

const isActive = wave.id === (searchParams?.get("wave") ?? undefined);
const isActive = wave.id === activeWaveId;

const onLinkClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();
router.push(getHref(wave.id));
};
const handleWaveClick = useCallback(
(event: React.MouseEvent<HTMLAnchorElement>) => {
if (event.defaultPrevented) return;
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button === 1) {
// let browser handle new tab/window
return;
}
event.preventDefault();
onWaveHover();
const nextWaveId = wave.id === activeWaveId ? null : wave.id;
activeWave.set(nextWaveId);
},
[activeWave.set, activeWaveId, onWaveHover, wave.id]
);

const getAvatarRingClasses = () => {
if (isActive) return "tw-ring-1 tw-ring-offset-2 tw-ring-offset-iron-900 tw-ring-primary-400";
Expand All @@ -93,9 +102,9 @@ const BrainLeftSidebarWave: React.FC<BrainLeftSidebarWaveProps> = ({
: "desktop-hover:hover:tw-bg-iron-800/80"
}`}>
<Link
href={getHref(wave.id)}
onMouseEnter={() => onWaveHover(wave.id)}
onClick={onLinkClick}
href={href}
onMouseEnter={onWaveHover}
onClick={handleWaveClick}
className={`tw-flex tw-flex-1 tw-space-x-3 tw-no-underline tw-py-1 tw-transition-all tw-duration-200 tw-ease-out ${
isActive
? "tw-text-white desktop-hover:group-hover:tw-text-white"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { useCallback, useMemo } from 'react';
import React, { useCallback, useMemo } from 'react';
import type { ReadonlyURLSearchParams } from 'next/navigation';

interface UseWaveNavigationOptions {
readonly basePath: string;
readonly activeWaveId: string | null;
readonly setActiveWave: (
waveId: string | null,
options?: { isDirectMessage?: boolean }
) => void;
readonly onHover: (waveId: string) => void;
readonly prefetchWaveData: (waveId: string) => void;
readonly searchParams: ReadonlyURLSearchParams | null;
Expand All @@ -13,16 +18,19 @@ interface UseWaveNavigationResult {
readonly href: string;
readonly isActive: boolean;
readonly onMouseEnter: () => void;
readonly onClick: (e: React.MouseEvent<HTMLAnchorElement>) => void;
}

export const useWaveNavigation = ({
basePath,
activeWaveId,
setActiveWave,
onHover,
prefetchWaveData,
searchParams,
waveId,
}: UseWaveNavigationOptions): UseWaveNavigationResult => {
const currentWaveId = searchParams?.get('wave') ?? undefined;
const currentWaveId = activeWaveId ?? searchParams?.get('wave') ?? undefined;

const href = useMemo(() => {
if (currentWaveId === waveId) {
Expand All @@ -45,9 +53,24 @@ export const useWaveNavigation = ({
prefetchWaveData(waveId);
}, [currentWaveId, onHover, prefetchWaveData, waveId]);

const onClick = useCallback(
(event: React.MouseEvent<HTMLAnchorElement>) => {
if (event.defaultPrevented) return;
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button === 1) {
return; // allow new-tab behavior
}
event.preventDefault();
onMouseEnter();
const nextWaveId = waveId === currentWaveId ? null : waveId;
setActiveWave(nextWaveId);
},
[currentWaveId, onMouseEnter, setActiveWave, waveId]
);

return {
href,
isActive,
onMouseEnter,
onClick,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ExpandedWave } from './subcomponents/ExpandedWave';
import { useWaveNavigation } from './hooks/useWaveNavigation';
import { useWaveNameTruncation } from './hooks/useWaveNameTruncation';
import { formatWaveName } from './utils/formatWaveName';
import { useMyStream } from '@/contexts/wave/MyStreamContext';

interface WebBrainLeftSidebarWaveProps {
readonly wave: MinimalWave;
Expand All @@ -29,12 +30,15 @@ const WebBrainLeftSidebarWave = ({
basePath = '/waves',
collapsed = false,
}: WebBrainLeftSidebarWaveProps) => {
const { activeWave } = useMyStream();
const searchParams = useSearchParams();
const prefetchWaveData = usePrefetchWaveData();
const { hasTouchScreen } = useDeviceInfo();

const { href, isActive, onMouseEnter } = useWaveNavigation({
const { href, isActive, onMouseEnter, onClick } = useWaveNavigation({
basePath,
activeWaveId: activeWave.id,
setActiveWave: activeWave.set,
onHover,
prefetchWaveData,
searchParams,
Expand Down Expand Up @@ -71,6 +75,7 @@ const WebBrainLeftSidebarWave = ({
isActive={isActive}
isDropWave={isDropWave}
onMouseEnter={onMouseEnter}
onClick={onClick}
showTooltip={showCollapsedTooltip}
tooltipId={tooltipId}
tooltipPlacement={TOOLTIP_PLACEMENT}
Expand All @@ -89,6 +94,7 @@ const WebBrainLeftSidebarWave = ({
latestDropTimestamp={wave.newDropsCount.latestDropTimestamp}
nameRef={nameRef}
onMouseEnter={onMouseEnter}
onClick={onClick}
showExpandedTooltip={showExpandedTooltip}
showPin={showPin}
tooltipContent={formattedWaveName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface CollapsedWaveProps {
readonly isActive: boolean;
readonly isDropWave: boolean;
readonly onMouseEnter: () => void;
readonly onClick: (e: React.MouseEvent<HTMLAnchorElement>) => void;
readonly showTooltip: boolean;
readonly tooltipId: string;
readonly tooltipPlacement: WaveTooltipPlacement;
Expand All @@ -23,6 +24,7 @@ export const CollapsedWave = ({
isActive,
isDropWave,
onMouseEnter,
onClick,
showTooltip,
tooltipId,
tooltipPlacement,
Expand All @@ -38,6 +40,7 @@ export const CollapsedWave = ({
<Link
href={href}
onMouseEnter={onMouseEnter}
onClick={onClick}
className="tw-flex tw-items-center tw-justify-center tw-no-underline"
{...(showTooltip ? { 'data-tooltip-id': tooltipId } : {})}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface ExpandedWaveProps {
readonly latestDropTimestamp?: number | null;
readonly nameRef: MutableRefObject<HTMLDivElement | null>;
readonly onMouseEnter: () => void;
readonly onClick: (e: React.MouseEvent<HTMLAnchorElement>) => void;
readonly showExpandedTooltip: boolean;
readonly showPin: boolean;
readonly tooltipContent: string;
Expand All @@ -35,6 +36,7 @@ export const ExpandedWave = ({
latestDropTimestamp,
nameRef,
onMouseEnter,
onClick,
showExpandedTooltip,
showPin,
tooltipContent,
Expand All @@ -61,6 +63,7 @@ export const ExpandedWave = ({
<Link
href={href}
onMouseEnter={onMouseEnter}
onClick={onClick}
className={`tw-flex tw-flex-1 tw-min-w-0 tw-space-x-3 tw-no-underline tw-py-1 tw-transition-all tw-duration-200 tw-ease-out ${
isActive
? 'tw-text-white desktop-hover:group-hover:tw-text-white tw-font-medium'
Expand Down
10 changes: 4 additions & 6 deletions components/header/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { capitalizeEveryWord, formatAddress } from "@/helpers/Helpers";
import { useIdentity } from "@/hooks/useIdentity";
import { useWaveById } from "@/hooks/useWaveById";
import { Bars3Icon } from "@heroicons/react/24/outline";
import { usePathname, useSearchParams } from "next/navigation";
import { usePathname } from "next/navigation";
import { useState } from "react";
import { useAuth } from "../auth/Auth";
import { useSeizeConnectContext } from "../auth/SeizeConnectContext";
Expand All @@ -15,17 +15,18 @@ import Spinner from "../utils/Spinner";
import AppSidebar from "./AppSidebar";
import HeaderSearchButton from "./header-search/HeaderSearchButton";
import HeaderActionButtons from "./HeaderActionButtons";
import { useMyStreamOptional } from "@/contexts/wave/MyStreamContext";

interface Props {
readonly extraClass?: string;
}

export default function AppHeader(props: Readonly<Props>) {
const [menuOpen, setMenuOpen] = useState(false);
const myStream = useMyStreamOptional();
const { address } = useSeizeConnectContext();
const { activeProfileProxy } = useAuth();
const pathname = usePathname();
const searchParams = useSearchParams();
const { profile } = useIdentity({
handleOrWallet: address ?? null,
initialProfile: null,
Expand All @@ -46,10 +47,7 @@ export default function AppHeader(props: Readonly<Props>) {
.replace(/^./, (c) => c.toUpperCase())
: "Home";

const waveId =
typeof searchParams?.get("wave") === "string"
? searchParams?.get("wave")
: null;
const waveId = myStream?.activeWave.id ?? null;
const { wave, isLoading, isFetching } = useWaveById(waveId);
const isProfileRoute = pathname?.startsWith("/[user]");
const isCreateRoute =
Expand Down
28 changes: 14 additions & 14 deletions components/providers/Providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,21 @@ export default function Providers({
<CookieConsentProvider>
<EULAConsentProvider>
<AppWebSocketProvider>
<TitleProvider>
<HeaderProvider>
<ScrollPositionProvider>
<ViewProvider>
<NavigationHistoryProvider>
<LayoutProvider>
<MyStreamProvider>
<LayoutProvider>
<MyStreamProvider>
<TitleProvider>
<HeaderProvider>
<ScrollPositionProvider>
<ViewProvider>
<NavigationHistoryProvider>
{children}
</MyStreamProvider>
</LayoutProvider>
</NavigationHistoryProvider>
</ViewProvider>
</ScrollPositionProvider>
</HeaderProvider>
</TitleProvider>
</NavigationHistoryProvider>
</ViewProvider>
</ScrollPositionProvider>
</HeaderProvider>
</TitleProvider>
</MyStreamProvider>
</LayoutProvider>
<NewVersionToast />
</AppWebSocketProvider>
</EULAConsentProvider>
Expand Down
6 changes: 3 additions & 3 deletions components/waves/WavesView.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
"use client";

import React from "react";
import { useSearchParams } from "next/navigation";
import { PlusIcon } from "@heroicons/react/24/outline";
import MyStreamWave from "../brain/my-stream/MyStreamWave";
import BrainContent from "../brain/content/BrainContent";
import { useAuth } from "../auth/Auth";
import useDeviceInfo from "../../hooks/useDeviceInfo";
import PrimaryButton from "../utils/button/PrimaryButton";
import useCreateModalState from "@/hooks/useCreateModalState";
import { useMyStreamOptional } from "@/contexts/wave/MyStreamContext";

const WavesView: React.FC = () => {
const searchParams = useSearchParams();
const myStream = useMyStreamOptional();
const { connectedProfile } = useAuth();
const { isApp } = useDeviceInfo();
const { openWave } = useCreateModalState();

const serialisedWaveId = searchParams?.get('wave') || null;
const serialisedWaveId = myStream?.activeWave.id ?? null;

const showPlaceholder = !serialisedWaveId && !isApp;

Expand Down
Loading