Skip to content
Open
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

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

2 changes: 1 addition & 1 deletion frontend/src/__tests__/components.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, act } from '@testing-library/react';
import React from 'react';

Expand Down
13 changes: 9 additions & 4 deletions frontend/src/app/activity/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,16 @@ export default function ActivityPage() {
setLoading(false);
}
},
[session?.publicKey],
[session],
);

useEffect(() => {
if (status !== "connected") return;
const controller = new AbortController();
setPage(1);
fetchActivity(1, activeTab, false, controller.signal);
const initLoad = async () => {
await fetchActivity(1, activeTab, false, controller.signal);
};
void initLoad();
return () => controller.abort();
}, [activeTab, status, fetchActivity]);

Expand Down Expand Up @@ -136,7 +138,10 @@ export default function ActivityPage() {
{TABS.map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
onClick={() => {
setActiveTab(tab.id);
setPage(1);
}}
className={`px-4 py-2 rounded-full text-sm font-medium transition-all whitespace-nowrap border ${
activeTab === tab.id
? "bg-accent text-white border-accent"
Expand Down
9 changes: 7 additions & 2 deletions frontend/src/app/streams/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,13 @@ export default function StreamDetailsPage() {
useEffect(() => {
if (streamEvents.length > 0) {
const controller = new AbortController();
fetchStream(controller.signal);
fetchEvents(eventsPage, controller.signal);
const updateData = async () => {
await Promise.all([
fetchStream(controller.signal),
fetchEvents(eventsPage, controller.signal),
]);
};
void updateData();
return () => controller.abort();
}
}, [streamEvents, fetchStream, fetchEvents, eventsPage]);
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/app/streams/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const TOKEN_DECIMALS = 7;
export default function CreateStreamPage() {
const { status, session } = useWallet();
const router = useRouter();
const [nowTimestamp] = useState(() => Date.now());
const [loading, setLoading] = useState(false);
const [txState, setTxState] = useState<"idle" | "signing" | "submitted" | "confirming">("idle");
const [formData, setFormData] = useState({
Expand Down Expand Up @@ -194,7 +195,7 @@ export default function CreateStreamPage() {
<div className="flex justify-between items-center text-sm">
<span className="text-slate-400">Estimated End Date</span>
<span className="font-medium">
{new Date(Date.now() + Number(formData.duration || 0) * 86400000).toLocaleDateString()}
{new Date(nowTimestamp + Number(formData.duration || 0) * 86400000).toLocaleDateString()}
</span>
</div>
</div>
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/app/streams/streams/[streamId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ export default function StreamDetailsPage({ params }: StreamDetailsPageProps) {
}, [isValidStreamId, streamId]);

React.useEffect(() => {
void loadStream();
const initLoad = async () => {
await loadStream();
};
void initLoad();
}, [loadStream]);

const depositedAmount = stream ? toDisplayAmount(stream.depositedAmount) : 0;
Expand Down
1 change: 0 additions & 1 deletion frontend/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { NotificationDropdown } from "./NotificationDropdown";
import Link from "next/link";
import { useWallet } from "@/context/wallet-context";
import { Button } from "./ui/Button";
import { ModeToggle } from "./ModeToggle";
import { WalletButton } from "./wallet/WalletButton";

Expand Down
9 changes: 6 additions & 3 deletions frontend/src/components/TransactionTracker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,12 @@ export default function TransactionTracker({
// Reset state when returning to idle
useEffect(() => {
if (status === "idle") {
setPollCount(0);
setStreamData(null);
setPreviousStreamData(null);
const timer = setTimeout(() => {
setPollCount(0);
setStreamData(null);
setPreviousStreamData(null);
}, 0);
return () => clearTimeout(timer);
}
}, [status]);

Expand Down
17 changes: 11 additions & 6 deletions frontend/src/components/dashboard/dashboard-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
const [showWizard, setShowWizard] = React.useState(false);
const [modal, setModal] = React.useState<ModalState>(null);

const [snapshot, setSnapshot] = React.useState<DashboardSnapshot | null>(null);
const [isSnapshotLoading, setIsSnapshotLoading] = React.useState(true);
const [snapshotError, setSnapshotError] = React.useState<string | null>(null);

const { events: streamEvents, connected, reconnecting, error } = useStreamEvents({
userPublicKeys: [session.publicKey],
autoReconnect: true,
Expand Down Expand Up @@ -472,9 +476,7 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
const [withdrawingIncomingStreamId, setWithdrawingIncomingStreamId] = React.useState<string | null>(null);
const [isFormSubmitting, setIsFormSubmitting] = React.useState(false);

const [snapshot, setSnapshot] = React.useState<DashboardSnapshot | null>(null);
const [isSnapshotLoading, setIsSnapshotLoading] = React.useState(true);
const [snapshotError, setSnapshotError] = React.useState<string | null>(null);


const safeLoadTemplates = (): StreamTemplate[] => {
try {
Expand Down Expand Up @@ -506,8 +508,11 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
};

React.useEffect(() => {
setTemplates(safeLoadTemplates());
setTemplatesHydrated(true);
const timer = setTimeout(() => {
setTemplates(safeLoadTemplates());
setTemplatesHydrated(true);
}, 0);
return () => clearTimeout(timer);
}, []);

React.useEffect(() => {
Expand All @@ -529,7 +534,7 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
} finally {
setIsSnapshotLoading(false);
}
}, [session.publicKey]);
}, [session.publicKey, setIsSnapshotLoading, setSnapshotError, setSnapshot]);

React.useEffect(() => {
let cancelled = false;
Expand Down
57 changes: 37 additions & 20 deletions frontend/src/components/stream-creation/StreamCreationWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,23 +125,33 @@ export const StreamCreationWizard: React.FC<StreamCreationWizardProps> = ({
const [walletBalanceError, setWalletBalanceError] = useState<string | null>(null);

React.useEffect(() => {
let timer: NodeJS.Timeout;
try {
const stored = localStorage.getItem(CUSTOM_TEMPLATE_STORAGE_KEY);
if (!stored) return;
const parsed = JSON.parse(stored);
if (!Array.isArray(parsed)) return;
const sanitized = parsed
.filter((item) => item && typeof item.id === "string" && typeof item.name === "string")
.map((item) => ({
id: item.id,
name: item.name,
description: item.description || "Saved custom template",
values: item.values || {},
} as StreamTemplate));
setCustomTemplates(sanitized);
if (stored) {
const parsed = JSON.parse(stored);
if (Array.isArray(parsed)) {
const sanitized = parsed
.filter((item) => item && typeof item.id === "string" && typeof item.name === "string")
.map((item) => ({
id: item.id,
name: item.name,
description: item.description || "Saved custom template",
values: item.values || {},
} as StreamTemplate));
timer = setTimeout(() => {
setCustomTemplates(sanitized);
}, 0);
}
}
} catch {
setCustomTemplates([]);
timer = setTimeout(() => {
setCustomTemplates([]);
}, 0);
}
return () => {
if (timer) clearTimeout(timer);
};
}, []);

React.useEffect(() => {
Expand All @@ -153,16 +163,22 @@ export const StreamCreationWizard: React.FC<StreamCreationWizardProps> = ({
}, [customTemplates]);

React.useEffect(() => {
let cancelled = false;
let timer: NodeJS.Timeout;

if (!walletPublicKey || !formData.token) {
setWalletBalance(null);
setWalletBalanceError(null);
setWalletBalanceLoading(false);
return;
timer = setTimeout(() => {
setWalletBalance(null);
setWalletBalanceError(null);
setWalletBalanceLoading(false);
}, 0);
return () => clearTimeout(timer);
}

let cancelled = false;
setWalletBalanceLoading(true);
setWalletBalanceError(null);
timer = setTimeout(() => {
setWalletBalanceLoading(true);
setWalletBalanceError(null);
}, 0);

fetchTokenBalanceDisplay(walletPublicKey, formData.token)
.then((balance) => {
Expand All @@ -181,6 +197,7 @@ export const StreamCreationWizard: React.FC<StreamCreationWizardProps> = ({

return () => {
cancelled = true;
clearTimeout(timer);
};
}, [walletPublicKey, formData.token]);

Expand Down
1 change: 0 additions & 1 deletion frontend/src/hooks/useStreamEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export function useStreamEvents(
): UseStreamEventsReturn {
const {
streamIds = [],
userPublicKeys = [],
subscribeToAll = false,
autoReconnect = true,
maxRetryDelay = 30000,
Expand Down
1 change: 0 additions & 1 deletion frontend/src/lib/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export interface DashboardAnalyticsMetric {
unavailableText: string;
}

const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001/v1";

function shortenAddress(address: string): string {
if (!address || address.length < 10) return address;
Expand Down
Loading
Loading